package com.jmga.ecogasfinder.activities.maps;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ZoomControls;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;
import com.jmga.ecogasfinder.R;
import com.jmga.ecogasfinder.activities.Preferences;
import com.jmga.ecogasfinder.activities.gasstation.GasStationFavouritesActivity;
import com.jmga.ecogasfinder.activities.gasstation.GasStationSummaryActivity;
import com.jmga.ecogasfinder.activities.maps.overlays.FinderLocationOverlay;
import com.jmga.ecogasfinder.activities.maps.overlays.GasStationsOverlay;
import com.jmga.ecogasfinder.activities.maps.overlays.RouteOverlay;
import com.jmga.ecogasfinder.providers.GasFinderProvider;
import com.jmga.ecogasfinder.receivers.AlarmsReceiver;
import com.jmga.ecogasfinder.services.CleaningService;
import com.jmga.ecogasfinder.services.LookupGasFinderService;
import com.jmga.ecogasfinder.services.StationUpdaterService;
import com.jmga.ecogasfinder.utilities.Tools;
import com.jmga.ecogasfinder.vo.GasStation;
import com.jmga.ecogasfinder.vo.SerializableGeoPoint;

public class ECOGasStationFinderMapActivity extends MapActivity {

	private static ArrayList<GasStation> gasStations = new ArrayList<GasStation>();
	private GasStation selectedGasStation;
	private GasStationReceiver gasStationReceiver;
	private PerformActionsReceiver actionsReceiver;
	private AlarmsReceiver alarmsReceiver;
	private MapView myMapView = null;
	private ImageView dataGreenTrafficImage = null, dataRedTrafficImage = null;
	private ImageButton favouriteButton;
	private MapController mapController;
	private GasStationsOverlay gasStationsOverlay, favouriteGasStationsOverlay;
	private static FinderLocationOverlay myLocationOverlay;
	private static Location myLocation;
	private float selectedLocLongitude, selectedLocLatitude;
	private GeoPoint routeStartPoint, routeEndPoint; 
	private int gasType = 1;
	private int lookUpAreaMeters = 2000;
	private int lookUpAreaRouteMeters = 500;

	private static final int MENU_FAVOURITES = Menu.FIRST;
	private static final int MENU_MY_POSITION = Menu.FIRST + 1;
	private static final int SEARCH_FROM_MY_POSITION = Menu.FIRST + 2;
	private static final int MENU_PREFERENCES = Menu.FIRST + 3;
	private static final int SHOW_PREFERENCES = 1;
	private static final double MAX_DISTANCE = 15;

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, MENU_FAVOURITES, Menu.NONE, R.string.menu_favourites);
		menu.add(0, MENU_MY_POSITION, Menu.NONE, R.string.menu_my_position); 
		menu.add(0, SEARCH_FROM_MY_POSITION, Menu.NONE, R.string.menu_search_from_my_position); 
		menu.add(0, MENU_PREFERENCES, Menu.NONE, R.string.menu_preferences); 
		
		return true;
	}
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		Log.d(getClass().getName(), "ECOGasStationFinderMapActivity super.onCreate()");
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		Tools.getInstance().setMapActivity(this);		
		showTopTen();
		
		dataRedTrafficImage = (ImageView) findViewById(R.id.dataRedConnImage);
		dataRedTrafficImage.setVisibility(View.INVISIBLE);
		dataGreenTrafficImage = (ImageView) findViewById(R.id.dataGreenConnImage);
		dataGreenTrafficImage.setVisibility(View.VISIBLE);
		
		myMapView = (MapView) findViewById(R.id.myMapView);
		mapController = myMapView.getController();
		myMapView.setSatellite(false);
        
        ZoomControls zoomControls = (ZoomControls) findViewById(R.id.zoomControls);
        zoomControls.setOnZoomInClickListener(new OnClickListener() {
                public void onClick(View v) {
                	myMapView.getController().zoomIn();
                }
        });
        zoomControls.setOnZoomOutClickListener(new OnClickListener() {
                public void onClick(View v) {
                	myMapView.getController().zoomOut();
                }
        });
		
		mapController.setZoom(13);
		
		if(myLocationOverlay == null) {
			myLocationOverlay = new FinderLocationOverlay(this, myMapView, false);
		}
	    // myLocationOverlay.enableCompass();
	    myLocationOverlay.enableMyLocation();
	    
	    myMapView.getOverlays().add(myLocationOverlay);

		LocationManager locationManager;
		String context = Context.LOCATION_SERVICE;
		locationManager = (LocationManager) getSystemService(context);

		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		criteria.setBearingRequired(false);
		criteria.setCostAllowed(true);
		criteria.setPowerRequirement(Criteria.POWER_LOW);
		String provider = locationManager.getBestProvider(criteria, true);

		if(myLocation == null) {
			Context applicationContext = getApplicationContext();
			SharedPreferences prefs = PreferenceManager
					.getDefaultSharedPreferences(applicationContext);
			myLocation = getLocationFromPreferences(prefs);
			
			updateWithNewLocation(myLocation);
		}
		
		locationManager.requestLocationUpdates(provider, 2000, 10,
				locationListener);
		
		createGasStationsOverlay();
		myMapView.setLongClickable(true);
		registerForContextMenu(myMapView);
		refreshMap();
	}
	
	private void showTopTen() {

		ContentResolver cr = getContentResolver();
		DecimalFormat df = new DecimalFormat();
        DecimalFormatSymbols symbols = new DecimalFormatSymbols();
        symbols.setDecimalSeparator(',');
        symbols.setGroupingSeparator(' ');
        df.setDecimalFormatSymbols(symbols);
		
        updateFromPreferences();
        
        String[] stationArgs = new String[1];
        String stations = "", stationWhere = GasFinderProvider.KEY_FAVOURITE + " = 1";
		Cursor stationCursor = getContentResolver().query(GasFinderProvider.CONTENT_URI_STATIONS, null, stationWhere, null, null);
		if(stationCursor.getCount() != 0) {
			while(stationCursor.moveToNext()) {
				String stationCoords = String.valueOf(stationCursor.getDouble(stationCursor.getColumnIndex(GasFinderProvider.KEY_X_COORD))) +
					String.valueOf(stationCursor.getDouble(stationCursor.getColumnIndex(GasFinderProvider.KEY_Y_COORD)));
				stations += "'" +  stationCoords + "',";
			}
		}
		stationCursor.close();
    	String where = GasFinderProvider.KEY_GAS_TYPE + " = '" + gasType + "'";
    	if(!stations.isEmpty()) {
    		stationArgs[0] = stations.substring(0, stations.length() - 1);
    		where += " AND " + GasFinderProvider.KEY_STATION + " IN (" + stationArgs[0] + ")";
    	}
    	
		String priceOrderAsc = GasFinderProvider.KEY_PRICE + " ASC";
		String dateOrderDesc = GasFinderProvider.KEY_DATE + " DESC";
		
		ContentProvider cp = getContentResolver().acquireContentProviderClient(GasFinderProvider.CONTENT_URI_PRICES).getLocalContentProvider();
		GasFinderProvider fld = (GasFinderProvider) cp;
		String dateHaving = GasFinderProvider.KEY_DATE + " = max(" + GasFinderProvider.KEY_DATE + ")";
		String dateGroupBy = GasFinderProvider.KEY_STATION;
		
		Cursor cursorPrice = fld.query(GasFinderProvider.CONTENT_URI_PRICES, null, where, null, dateGroupBy, dateHaving, priceOrderAsc); 
		
		String stationString = "", idString = ""; 
		double firstPriceValue = 0d, secondPriceValue = 0d;
		float differencePrice = 0f;
		Date firstPriceDateValue = null, secondPriceDateValue = null;
			
		if(cursorPrice.getCount() != 0) {
			cursorPrice.moveToNext();
            String priceValueString = cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_PRICE));
            stationString = cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_STATION));
            idString = cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_ID));
            
			
			try {
				firstPriceValue = (Double) df.parse(priceValueString);
			} catch (ParseException e) {
				firstPriceValue = 0d;
				Log.d(getClass().getName(), "Exception caughted " + e.getLocalizedMessage());
			}
			SimpleDateFormat sdf2 = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault());
			firstPriceDateValue = new Date(Long.parseLong(cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_DATE))));
			String formattedDate = sdf2.format(firstPriceDateValue); 
			
			String cheapestString = cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_ID)) + " " + formattedDate
				 + " " + cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_STATION)) +  " " 
				 + firstPriceValue;
			Log.d(getClass().getName(), "Cheapest price " + cheapestString);
		}
		
		cursorPrice.close();
		
		cursorPrice = cr.query(GasFinderProvider.CONTENT_URI_PRICES, null, where + " AND " + GasFinderProvider.KEY_STATION + "= '" + 
						stationString + "' AND " + GasFinderProvider.KEY_ID + "<> '" + idString + "'", null, dateOrderDesc);
		if(cursorPrice.getCount() != 0) {
			cursorPrice.moveToNext();
			String priceValueString = cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_PRICE));
            stationString = cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_STATION));
            idString = cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_ID));
            
			try {
				secondPriceValue = (Double) df.parse(priceValueString);
			} catch (ParseException e) {
				secondPriceValue = 0d;
				Log.d(getClass().getName(), "Exception caughted " + e.getLocalizedMessage());
			}
			SimpleDateFormat sdf2 = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault());
			secondPriceDateValue = new Date(Long.parseLong(cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_DATE))));
			String formattedDate = sdf2.format(secondPriceDateValue); 
			
			String cheapestString = cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_ID)) + " " + formattedDate
				 + " " + cursorPrice.getString(cursorPrice.getColumnIndexOrThrow(GasFinderProvider.KEY_STATION)) +  " " 
				 + secondPriceValue;
			
			Log.d(getClass().getName(), " 2nd Cheapest price " + cheapestString);
		}
		
		cursorPrice.close();
		
		Button topTenButton = (Button) findViewById(R.id.topTenButton);
		String cheapestText = " " + getString(R.string.sameLabel) + " ";

		if(firstPriceDateValue != null && secondPriceDateValue != null) {
			differencePrice = (float) (firstPriceValue - secondPriceValue);
		}
		
		
		if(differencePrice > 0) {
			cheapestText = " " + getString(R.string.goingUpLabel) + " ";
		} else if(differencePrice < 0) {
			cheapestText = " " + getString(R.string.goingDownLabel) + " ";
		}
		
		topTenButton.setText(cheapestText + " " + firstPriceValue + getString(R.string.euroCurrencyLabel) + " (" 
				+ differencePrice + getString(R.string.euroCurrencyLabel) + ") ");
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		Log.d(getClass().getName(), "onCreateContextMenu:");
		super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater cntmenu = getMenuInflater();
        cntmenu.inflate(R.menu.map_contextmenu, menu);
	}
	
	@Override
	public boolean onContextItemSelected(MenuItem item) {
		super.onContextItemSelected(item);
		Projection projection = myMapView.getProjection();
		GeoPoint point = projection.fromPixels(Double.valueOf(selectedLocLongitude).intValue(), Double.valueOf(selectedLocLatitude).intValue());
		switch (item.getItemId()) {
			case (R.id.search):
				mapController.animateTo(point);
				Location l = new Location("Selected Point");
				l.setLongitude(point.getLongitudeE6() / 1E6);
				l.setLatitude(point.getLatitudeE6() / 1E6);

				myLocationOverlay.setLastLocationKnown(l);
				// remove all stations
				gasStations.clear();
				gasStationsOverlay.clearItems();
				refreshMap();
				lookUpGasStations(point, lookUpAreaMeters);
				return true;
			case (R.id.route_start):
				routeStartPoint = point;
				checkRoute();
				return true;
			case (R.id.route_end):
				routeEndPoint = point;
				checkRoute();
				return true;
		}
		return false;
	}

	private void checkRoute() {
	
		if(routeStartPoint != null && routeEndPoint != null) {
			RouteOverlay rOverlay = new RouteOverlay(routeStartPoint, routeEndPoint, getString(R.string.gmaps_feed));
			
			if(myMapView.getOverlays().get(0) instanceof RouteOverlay) {
				myMapView.getOverlays().remove(0);
			}

			myMapView.getOverlays().add(0, rOverlay);
			myMapView.invalidate();
			
			String rectPerimeter = String.valueOf(rOverlay.getyMax() / 1E6) + "," + String.valueOf(rOverlay.getxMax() / 1E6);
			rectPerimeter += "," + String.valueOf(rOverlay.getyMin() / 1E6) + "," + String.valueOf(rOverlay.getxMin() / 1E6);
			
			Log.d(getClass().getName(), "Distancia entre los dos puntos de la ruta solicitada = " + rOverlay.getDistance());
			
			if(rOverlay.getDistance() < MAX_DISTANCE) {
				lookUpGasStations(rectPerimeter, lookUpAreaRouteMeters);
			} else {
				lookUpGasStationsLarge(rOverlay.getGeoRoutePoints(), lookUpAreaRouteMeters);
			}

			routeStartPoint = null;
			routeEndPoint = null;
		}
	}

	private void lookUpGasStationsLarge(
			List<SerializableGeoPoint> geoRoutePoints,
			int lookUpAreaRouteMeters) {
		int halfway = geoRoutePoints.size()/2;
		double distance = Tools.getDistanceDriving(getString(R.string.gmaps_feed), geoRoutePoints.get(0).getGeoPoint(), geoRoutePoints.get(halfway).getGeoPoint());
		
		if(distance <= MAX_DISTANCE) {
			lookUpGasStationBaseCase(0, halfway, geoRoutePoints);
			lookUpGasStationBaseCase(halfway, geoRoutePoints.size(), geoRoutePoints);
			distance = Tools.getDistanceDriving(getString(R.string.gmaps_feed), geoRoutePoints.get(0).getGeoPoint(), geoRoutePoints.get(halfway).getGeoPoint());
		} else {
			lookUpGasStationsLarge(geoRoutePoints.subList(0, halfway), lookUpAreaRouteMeters);
		}
	}

	private void lookUpGasStationBaseCase(int start, int end, List<SerializableGeoPoint> geoRoutePoints) {
		Integer xMin = null, xMax = null, yMin = null, yMax = null;
		for(int i = start; i < end; i++) {
			SerializableGeoPoint p = geoRoutePoints.get(i);
			xMin = Tools.checkCoord(xMin, p.getLongitudeE6(), true);
			xMax = Tools.checkCoord(xMax, p.getLongitudeE6(), false);
			yMin = Tools.checkCoord(yMin, p.getLatitudeE6(), true);
			yMax = Tools.checkCoord(yMax, p.getLatitudeE6(), false);
		}
		String rectPerimeter = String.valueOf(yMax / 1E6) + "," + String.valueOf(xMax / 1E6);
		rectPerimeter += "," + String.valueOf(yMin / 1E6) + "," + String.valueOf(xMin / 1E6);
		
		lookUpGasStations(rectPerimeter, lookUpAreaRouteMeters);
	}

	private void createGasStationsOverlay() {
		Drawable blackPump = this.getResources().getDrawable(
				R.drawable.black_gas_pump);
		gasStationsOverlay = new GasStationsOverlay(Tools.getBitmapDrawableScaled(blackPump), this);
	}
	
	private void createFavouriteGasStationsOverlay() {
		Drawable greenPump = this.getResources().getDrawable(
				R.drawable.green_gas_pump);
		favouriteGasStationsOverlay = new GasStationsOverlay(Tools.getBitmapDrawableScaled(greenPump), this);
	}

	private void lookUpGasStations(GeoPoint geoPoint, int lookUpAreaMeters) {
		String rectPerimeter = getRectPerimeterByCoord(geoPoint.getLongitudeE6() / 1E6,
				geoPoint.getLatitudeE6() / 1E6, lookUpAreaMeters);
				
		lookUpGasStations(rectPerimeter, lookUpAreaMeters);
	}
	
	private void lookUpGasStations(String rectPerimeter, int lookUpAreaMeters) {
		Intent intent = new Intent(this, LookupGasFinderService.class);
		intent.putExtra(Preferences.PREF_GAS_TYPE, gasType);
		intent.putExtra(LookupGasFinderService.PERIMETER_SEARCH, rectPerimeter);
		intent.putExtra(LookupGasFinderService.LOOKUP_AREA_METERS, lookUpAreaMeters);
		
		startService(intent);
	}
	
	private void setFavourite(GasStation gasStation, boolean isFavourite) {
		Intent intent = new Intent(this, LookupGasFinderService.class);
		intent.putExtra(GasFinderProvider.KEY_STATION, gasStation);
		intent.putExtra(GasFinderProvider.KEY_FAVOURITE, isFavourite);
		startService(intent);
	}
	
	private void setRegular(GasStation gasStation) {
		Intent intent = new Intent(this, LookupGasFinderService.class);
		intent.putExtra(GasFinderProvider.KEY_STATION, gasStation);
		intent.putExtra(GasFinderProvider.KEY_REGULAR, Boolean.TRUE);
		startService(intent);
	}	
	
	public String getRectPerimeterByCoord(double myLocLongitude, double myLocLatitude, int meters) {
		Point centerPoint = new Point();
		
		Projection projection = myMapView.getProjection();
		GeoPoint myLocGeoPoint = new GeoPoint(Double.valueOf(myLocLatitude * 1E6).intValue(), Double.valueOf(myLocLongitude * 1E6).intValue());
		projection.toPixels(myLocGeoPoint, centerPoint);

		int northY = centerPoint.y - (int) projection.metersToEquatorPixels(meters);
		int southY = centerPoint.y + (int) projection.metersToEquatorPixels(meters);

		int westX = centerPoint.x - (int) projection.metersToEquatorPixels(meters);
		int eastX = centerPoint.x + (int) projection.metersToEquatorPixels(meters);
		
		GeoPoint leftTop = projection.fromPixels(westX, northY);
		GeoPoint rightBottom = projection.fromPixels(eastX, southY);
		
		String result = String.valueOf(leftTop.getLongitudeE6() / 1E6) + "," + String.valueOf(leftTop.getLatitudeE6() / 1E6);
		result += "," + String.valueOf(rightBottom.getLongitudeE6() / 1E6) + "," + String.valueOf(rightBottom.getLatitudeE6() / 1E6);
		
		return result;
	}
	
	private void refreshMap() {
		Log.d(getClass().getName(), "refreshMap:");
		List<Overlay> overlays = myMapView.getOverlays();
		
		overlays.clear();
		myMapView.invalidate();
		
		Drawable greenPump = this.getResources().getDrawable(
				R.drawable.green_gas_pump);
		Drawable bluePump = this.getResources().getDrawable(
				R.drawable.blue_gas_pump);
		Drawable clear = this.getResources().getDrawable(
				R.drawable.clear);
		double minDist = Double.MAX_VALUE;
		int ecoIndex = -1;
		
		for (GasStation gasStation : gasStations) {
			Double longitude = Double.valueOf(gasStation.getXCoord()) * 1E6;
			Double latitude = Double.valueOf(gasStation.getYCoord()) * 1E6;
			GeoPoint geoPoint = new GeoPoint(latitude.intValue(), longitude.intValue());
			String stationPerimeter = getRectPerimeterByCoord(Double.valueOf(gasStation.getXCoord()), Double.valueOf(gasStation.getYCoord()), 5);

			OverlayItem overlayitem = new OverlayItem(geoPoint,
					String.valueOf(gasStation.getPrice()), gasStation.isFavourite() + "@@" + stationPerimeter +
						"@@" + gasStation.getXCoord() + "@@" + gasStation.getYCoord());
			
			gasStation.setXkey(stationPerimeter);
			setRegular(gasStation);
			
			Drawable drawable = null;
			if(gasStations.indexOf(gasStation) == (gasStations.size() - 1)) {
				drawable = (longitude != 0 && latitude != 0) ? Tools.getBitmapDrawableScaled(bluePump): Tools.getBitmapDrawableScaled(clear);
			}
			Location location = new Location("dummyGPS");
	        location.setLongitude(Double.parseDouble(gasStation.getXCoord()));
	        location.setLatitude(Double.parseDouble(gasStation.getYCoord()));
	        
			double dist = Tools.getDistanceDriving(getString(R.string.gmaps_feed), myLocation, location);
			if(dist < minDist) {
				minDist = dist;
				ecoIndex = gasStations.indexOf(gasStation);
			}
			gasStationsOverlay.addOverlay(overlayitem, drawable);
		}
		
		if(ecoIndex != -1){
			GasStation gasStation = gasStations.get(ecoIndex);
			Double longitude = Double.valueOf(gasStation.getXCoord()) * 1E6;
			Double latitude = Double.valueOf(gasStation.getYCoord()) * 1E6;
			GeoPoint geoPoint = new GeoPoint(latitude.intValue(), longitude.intValue());
			String stationPerimeter = getRectPerimeterByCoord(Double.valueOf(gasStation.getXCoord()),Double.valueOf(gasStation.getYCoord()),5);
			
			OverlayItem overlayitem = new OverlayItem(geoPoint,
					String.valueOf(gasStation.getPrice()), gasStation.isFavourite() + "@@" + stationPerimeter +
						"@@" + gasStation.getXCoord() + "@@" + gasStation.getYCoord());
			
			Drawable drawable = Tools.getBitmapDrawableScaled(greenPump);
			gasStationsOverlay.addOverlay(overlayitem, drawable);
		}
		
		
		
		
		overlays.add(gasStationsOverlay);
		overlays.add(myLocationOverlay);
		
		myMapView.postInvalidate();
	}


	private final LocationListener locationListener = new LocationListener() {
		public void onLocationChanged(Location location) {
			Log.d(getClass().getName(), "onLocationChanged");
			updateWithNewLocation(location);
		}

		public void onProviderDisabled(String provider) {
			Log.d(getClass().getName(), "onProviderDisabled");
			updateWithNewLocation(null);
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
	};

	private void updateWithNewLocation(Location location) {
		if (location != null) {
			if(gasStationsOverlay == null) {
				createGasStationsOverlay();
			}

			// Double geoLat = location.getLatitude() * 1E6;
			// Double geoLng = location.getLongitude() * 1E6;
			// GeoPoint point = new GeoPoint(geoLat.intValue(), geoLng.intValue());

			// mapController.animateTo(point);
			myLocationOverlay.setLastLocationKnown(location);
			myLocation = location;
			
			// lookUpGasStations(point, lookUpAreaMeters);
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);
		Intent i;
		
		switch (item.getItemId()) {
		case (MENU_FAVOURITES): {
			i = new Intent(this, GasStationFavouritesActivity.class);
			startActivity(i);
			return true;
		}
		case (MENU_MY_POSITION): {
			Double geoLat = myLocation.getLatitude() * 1E6;
			Double geoLng = myLocation.getLongitude() * 1E6;
			GeoPoint point = new GeoPoint(geoLat.intValue(), geoLng.intValue());

			mapController.animateTo(point);
			return true;
		}
		case (SEARCH_FROM_MY_POSITION): {
			Double geoLat = myLocation.getLatitude() * 1E6;
			Double geoLng = myLocation.getLongitude() * 1E6;
			GeoPoint point = new GeoPoint(geoLat.intValue(), geoLng.intValue());

			mapController.animateTo(point);
			lookUpGasStations(point, lookUpAreaMeters);
			return true;
		}		
		case (MENU_PREFERENCES): {
			i = new Intent(this, Preferences.class);
			startActivityForResult(i, SHOW_PREFERENCES);
			return true;
		}
		}
		return false;
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if (requestCode == SHOW_PREFERENCES) {
			updateFromPreferences();
		}
	}
	
	private void updateFromPreferences() {
		Context context = getApplicationContext();
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(context);

		gasType = Integer.parseInt(prefs.getString(Preferences.PREF_GAS_TYPE, "1"));
		lookUpAreaMeters = Integer.parseInt(prefs.getString(Preferences.PREF_LOOKUP_AREA, "2000"));
		lookUpAreaRouteMeters = Integer.parseInt(prefs.getString(Preferences.PREF_LOOKUP_AREA_ROUTE, "500"));
		
		if(myLocation == null) {
			myLocation = getLocationFromPreferences(prefs);
		}
		
		int cleanNow = Integer.parseInt(prefs.getString(Preferences.PREF_CLEANING_NOW, "2"));
		int whenCleaning = Integer.parseInt(prefs.getString(Preferences.PREF_CLEANING_VALIDITY_ELEMENTS, "7"));
		boolean favouritesCleaning = prefs.getBoolean(Preferences.PREF_CLEANING_FAVOURITES, false);
		boolean pricesCleaning = prefs.getBoolean(Preferences.PREF_CLEANING_PRICES, false);
		
		if (cleanNow == 1 && whenCleaning != 7 && (favouritesCleaning || pricesCleaning)) {
			Log.d(getClass().getName(), "Cleaning data");
			
			Intent intent = new Intent(this, CleaningService.class);
			intent.putExtra(CleaningService.KEY_WHEN, whenCleaning);
			intent.putExtra(CleaningService.KEY_CHECKBOX_FAVOURITE, favouritesCleaning);
			intent.putExtra(CleaningService.KEY_CHECKBOX_PRICES, pricesCleaning);

			startService(intent);
			
			Editor prefsEditor = prefs.edit();
			prefsEditor.putString(Preferences.PREF_CLEANING_NOW,"2");
			boolean success = prefsEditor.commit();
			if(!success) {
				Log.e(getClass().getName(), "Preferences's not stored succesfully after commit");
			}
		} else {
			Log.d(getClass().getName(), "NOT Cleaning data");
		}
	}
	
    private Location getLocationFromPreferences(SharedPreferences prefs) {
		LocationManager locationManager;
		String locationContext = Context.LOCATION_SERVICE;
		locationManager = (LocationManager) getSystemService(locationContext);
		
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		criteria.setBearingRequired(false);
		criteria.setCostAllowed(true);
		criteria.setPowerRequirement(Criteria.POWER_LOW);
		String provider = locationManager.getBestProvider(criteria, true);
		
		Location result = new Location(provider);
		
		String preferencesLocation = prefs.getString(Preferences.PREF_DEFAULT_LOCATION, "37.352253,-5.960324");
		String[] splittedLocation = preferencesLocation.split(",");
		
		if(splittedLocation.length == 2) {
			result.setLatitude(Double.parseDouble(splittedLocation[0]));
			result.setLongitude(Double.parseDouble(splittedLocation[1]));
		} else {
			try {
				String url = getString(R.string.gmaps_geocode_adress_feed) + preferencesLocation;
				String geoLocation = Tools.getLocationLatLong(Tools.getLocationInfo(url));
				splittedLocation = geoLocation.split(",");
				result.setLatitude(Double.parseDouble(splittedLocation[0]));
				result.setLongitude(Double.parseDouble(splittedLocation[1]));
				
			} catch (Exception e) {
				e.printStackTrace();
				result.setLatitude(37.352253);
				result.setLongitude(-5.960324);
			}
		}

		return result;
	}

	public class GasStationReceiver extends BroadcastReceiver {
        @Override
        public synchronized void onReceive(Context context, Intent intent) {
            if(intent.getAction().equals(LookupGasFinderService.STARTED_LOADING)) {
            	myMapView.getOverlays().clear();
            	dataRedTrafficImage.setVisibility(View.VISIBLE);
            	dataGreenTrafficImage.setVisibility(View.INVISIBLE);
            } else if(intent.getAction().equals(LookupGasFinderService.FINISHED_LOADING)) {
            	dataRedTrafficImage.setVisibility(View.INVISIBLE);
            	dataGreenTrafficImage.setVisibility(View.VISIBLE);
            } else if(intent.getAction().equals(LookupGasFinderService.UPDATE_GAS_STATION_FOUND)) {
            	GasStation gasStation = (GasStation) intent.getSerializableExtra(GasFinderProvider.KEY_STATION);
            	Log.d(getClass().getName(), "onReceive (UPDATE_GAS_STATION_FOUND):" + gasStation.getXkey());
            	int pos = searchByCoords(gasStation.getXCoord(), gasStation.getYCoord());
            	
            	if(pos != 1) {
            		gasStations.add(pos, gasStation);
                	gasStations.remove(pos + 1);
            	}
            	
            	refreshMap();
            } else if(intent.getAction().equals(LookupGasFinderService.NEW_GAS_STATION_FOUND)) {
	        	GasStation gasStation = (GasStation) intent.getSerializableExtra(GasFinderProvider.KEY_STATION);
	        	Log.d(getClass().getName(), "onReceive (NEW_GAS_STATION_FOUND):" + gasStation.getXkey() + ":" + gasStation.getPrice() + ":" + gasStation.getDate());
	
	        	// The cheapest station will be in the last position
	            int size = gasStations.size();
	            if(size > 0 && gasStation.getXkey() != null && !gasStation.getXkey().isEmpty() && (gasStations.indexOf(gasStation) == -1)) {
	            	GasStation cheapest = gasStations.get(size - 1);
	            	if(gasStation.getPrice() <= cheapest.getPrice()) {
	            		gasStations.add(gasStation);
	            	} else {
	            		gasStations.add(size - 1, gasStation);
	            	}
	            } else if (size == 0 && gasStation.getXkey() != null && !gasStation.getXkey().isEmpty()){
	            	gasStations.add(gasStation);
	            }
	            refreshMap();
            }
        }
    }
    
    public class PerformActionsReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			if(intent.getAction().equals(GasStationsOverlay.OPEN_CONTEXT_MENU_ACTION)) {
				Log.d(getClass().getName(), "Showing Context Menu");
				selectedLocLongitude = intent.getFloatExtra(GasStationsOverlay.X_COORD_POINTED, 0f);
				selectedLocLatitude = intent.getFloatExtra(GasStationsOverlay.Y_COORD_POINTED, 0f);
				
				openContextMenu(myMapView);
			} else if(intent.getAction().equals(GasStationsOverlay.SET_FAVOURITE_ACTION)) {
				double longitude = (double) intent.getIntExtra(GasStationsOverlay.X_COORD_POINTED, 0) / 1000000;
				double latitude = (double) intent.getIntExtra(GasStationsOverlay.Y_COORD_POINTED, 0) / 1000000;
				String xkey = intent.getStringExtra(GasFinderProvider.KEY_XKEY);
				boolean isFavourite = intent.getBooleanExtra(GasFinderProvider.KEY_FAVOURITE, false);
				Log.d(getClass().getName(), "Set Favourite to " + isFavourite);
				int pos = searchByCoords(String.valueOf(longitude), String.valueOf(latitude));
				
				if(pos !=  -1) {
					GasStation station = gasStations.get(pos);
					station.setXkey(xkey);
					setFavourite(station, isFavourite);
				} else if(!isFavourite) {
					setFavourite(getSelectedGasStation(), isFavourite);
				}
			} else if(intent.getAction().equals(GasStationsOverlay.GET_ROUTE_ACTION)) {
				int longitude = intent.getIntExtra(GasStationsOverlay.X_COORD_POINTED, 0);
				int latitude = intent.getIntExtra(GasStationsOverlay.Y_COORD_POINTED, 0);

				if (myLocationOverlay != null) {
					GeoPoint geoPointB = new GeoPoint(latitude, longitude);
			
					RouteOverlay rOverlay = new RouteOverlay(myLocationOverlay.getLastLocationKnown(), geoPointB, getString(R.string.gmaps_feed));
					if(myMapView.getOverlays().get(0) instanceof RouteOverlay) {
						myMapView.getOverlays().remove(0);
					}

					myMapView.getOverlays().add(0,rOverlay);
					myMapView.invalidate();
				}
			} else if(intent.getAction().equals(StationUpdaterService.SHOW_TOP_TEN)) {
				showTopTen();
			}
		}
    	
    }
    
    @Override 
    public void onResume() {
    	Log.d(getClass().getName(), "ECOGasStationFinderMapActivity onResume");
    	IntentFilter filter;
    	filter = new IntentFilter(LookupGasFinderService.STARTED_LOADING);
    	gasStationReceiver = new GasStationReceiver();
    	registerReceiver(gasStationReceiver, filter);
    	filter = new IntentFilter(LookupGasFinderService.FINISHED_LOADING);
    	registerReceiver(gasStationReceiver, filter);
    	filter = new IntentFilter(LookupGasFinderService.NEW_GAS_STATION_FOUND);
    	registerReceiver(gasStationReceiver, filter);
    	filter = new IntentFilter(LookupGasFinderService.UPDATE_GAS_STATION_FOUND);
    	registerReceiver(gasStationReceiver, filter);
    	filter = new IntentFilter(GasStationsOverlay.OPEN_CONTEXT_MENU_ACTION);
    	actionsReceiver = new PerformActionsReceiver();
    	registerReceiver(actionsReceiver, filter);
    	filter = new IntentFilter(GasStationsOverlay.SET_FAVOURITE_ACTION);
    	registerReceiver(actionsReceiver, filter);
    	filter = new IntentFilter(GasStationsOverlay.GET_ROUTE_ACTION);
    	registerReceiver(actionsReceiver, filter);
    	alarmsReceiver = new AlarmsReceiver();
    	filter = new IntentFilter(AlarmsReceiver.ONE_TIME);
    	registerReceiver(alarmsReceiver, filter);
    	filter = new IntentFilter(StationUpdaterService.SHOW_TOP_TEN);
    	registerReceiver(actionsReceiver, filter);
    	
    	super.onResume();
    }

    public int searchByCoords(String xCoord, String yCoord) {
    	int result = -1;
		for (int i = 0; i < gasStations.size(); i++) {
			if(gasStations.get(i).getXCoord().indexOf(xCoord) != -1 && gasStations.get(i).getYCoord().indexOf(yCoord) != -1) {
				result = i;
				break;
			}
		}
		
		return result;
	}

	@Override
    public void onPause() {
    	Log.d(getClass().getName(), "ECOGasStationFinderMapActivity onPause");
    	unregisterReceiver(gasStationReceiver);
    	unregisterReceiver(actionsReceiver);
    	// we won't unregister alarmsReceiver obviously
    	super.onPause();
    }
	
	@Override
	protected void onDestroy() {
		Log.d(getClass().getName(), "ECOGasStationFinderMapActivity super.onDestroy()");
		unregisterReceiver(alarmsReceiver);
		super.onDestroy();
	}

	@Override
	protected void onRestart() {
		Log.d(getClass().getName(), "ECOGasStationFinderMapActivity super.onRestart()");
		super.onRestart();
	}

	@Override
	protected void onStart() {
		Log.d(getClass().getName(), "ECOGasStationFinderMapActivity super.onStart()");
		super.onStart();
	}

	@Override
	protected void onStop() {
		Log.d(getClass().getName(), "ECOGasStationFinderMapActivity super.onStop()");
		super.onStop();
	}
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		Log.d(getClass().getName(), "ECOGasStationFinderMapActivity super.onRestoreInstanceState()");
		super.onRestoreInstanceState(savedInstanceState);
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		Log.d(getClass().getName(), "ECOGasStationFinderMapActivity super.onSaveInstanceState()");
		super.onSaveInstanceState(outState);
	}
	
	
	public GasStation getSelectedGasStation() {
		return selectedGasStation;
	}
	
	public void setSelectedGasStation(GasStation gasStation) {
		this.selectedGasStation = gasStation;
	}

	public void setSelectedGasStationByCoords(String xCoord, String yCoord, String xkey) {
		int index = searchByCoords(xCoord, yCoord);
		if(index != -1) {
			this.selectedGasStation = gasStations.get(index);
			if(!this.selectedGasStation.getXkey().equals(xkey)) {
				this.selectedGasStation.setXkey(xkey);
			}
		} else {
	    	String labelString = null, operatorString = null, addressString = null, laneString = null, postalCodeString = null, provinceString = null,
    		localityString = null, saleTypeString = null, sentTypeString = null;
	    	Date fecha = null;
	    	float price = 0f;
	        
	    	String whereStation = GasFinderProvider.KEY_X_COORD + " = '" + xCoord + "' AND " + 
	    		GasFinderProvider.KEY_Y_COORD + " = '" + yCoord + "'";
	    	
	    	Cursor cursor = getContentResolver().query(GasFinderProvider.CONTENT_URI_STATIONS, null, whereStation, null, null); 
	    	cursor.moveToNext();
	    	
	        labelString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_LABEL));
	        operatorString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_OPERATOR));
	        addressString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_ADDRESS));
	        laneString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_LANE));
	        postalCodeString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_POSTAL_CODE));
	        provinceString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_PROVINCE));
	        localityString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_LOCALITY));
	        saleTypeString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_SALE_TYPE));
	        sentTypeString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_SENT_TYPE));
	        
	        String referencia = xCoord + yCoord;
	        
	        //finding the last price and date from price table
	        Context context = getApplicationContext();
	        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
			int gasType = Integer.parseInt(prefs.getString(Preferences.PREF_GAS_TYPE, "1"));
	        
	        String where = GasFinderProvider.KEY_STATION + " = '" + referencia + "' AND " + 
	        	GasFinderProvider.KEY_GAS_TYPE + " = '" + gasType + "'";
	        String priceOrder = GasFinderProvider.KEY_PRICE + " DESC";
	        Cursor cursorPrice = getContentResolver().query(GasFinderProvider.CONTENT_URI_PRICES, null, where, null, priceOrder);
	        
	        DecimalFormat df = new DecimalFormat();
	        DecimalFormatSymbols symbols = new DecimalFormatSymbols();
	        symbols.setDecimalSeparator(',');
	        symbols.setGroupingSeparator(' ');
	        df.setDecimalFormatSymbols(symbols);
	        
	        if(cursorPrice.getCount() != 0) {
	        	cursorPrice.moveToNext();
				String priceValueString = cursorPrice.getString(3);
				
				double priceValue;
				try {
					priceValue = (Double) df.parse(priceValueString);
				} catch (ParseException e) {
					priceValue = 0d;
					Log.d(getClass().getName(), "Exception caughted " + e.getLocalizedMessage());
				}
				fecha = new Date(Long.parseLong(cursorPrice.getString(1)));
				price = (float) priceValue;
	        } else {
	        	fecha = new Date();
	        }
	        
	        this.selectedGasStation = new GasStation(labelString, operatorString, addressString,
					laneString,	postalCodeString, provinceString, localityString, fecha,
					saleTypeString,	sentTypeString, xCoord, yCoord, xkey, price);
		}
	}

  	public void showSummary(View view) {
		Intent intent = new Intent(this, GasStationSummaryActivity.class);
  		startActivity(intent);
  	}
  	
  	public void showOptionsMenu(View view) {
  		Log.d(getClass().getName(), "Showing Options Menu By Button");
		this.getWindow().openPanel(Window.FEATURE_OPTIONS_PANEL, null);
  	}
  	
	public void showFavourites(View view) {
		Log.d(getClass().getName(), "Showing Favourites Gas Stations");
		if(favouriteGasStationsOverlay == null) {
			createFavouriteGasStationsOverlay();
		}
		
		favouriteButton = (ImageButton) findViewById(R.id.favouritesButtonEmpty);
		
		if(favouriteButton.getVisibility() == View.INVISIBLE) {
			favouriteButton.setVisibility(View.VISIBLE);
			favouriteGasStationsOverlay.clearItems();
			myMapView.invalidate();
		} else {
			favouriteButton.setVisibility(View.INVISIBLE);
			String whereFavourite = GasFinderProvider.KEY_FAVOURITE + " = 1 ";
			Cursor cursor = getContentResolver().query(GasFinderProvider.CONTENT_URI_STATIONS, null, whereFavourite, null, null); 
		    
			List<Overlay> overlays = myMapView.getOverlays();
			
			Drawable yellowPump = this.getResources().getDrawable(
					R.drawable.yellow_gas_pump);
			
			Drawable drawable = Tools.getBitmapDrawableScaled(yellowPump);
			
			String xCoordString = null, yCoordString = null;
			float price = 0f;
			
			if(cursor.getCount() != 0) {
				for(int i=0; cursor.moveToNext(); i++) {
				    double xCoord = cursor.getDouble(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_X_COORD));
				    double yCoord = cursor.getDouble(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_Y_COORD));
				    xCoordString = String.valueOf(xCoord);
				    yCoordString = String.valueOf(yCoord);
			    
			    	String referencia = xCoordString + yCoordString;
			    
				    //finding the last price and date from price table
				    Context context = getApplicationContext();
				    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
					int gasType = Integer.parseInt(prefs.getString(Preferences.PREF_GAS_TYPE, "1"));
			    
				    String where = GasFinderProvider.KEY_STATION + " = '" + referencia + "' AND " + 
				    	GasFinderProvider.KEY_GAS_TYPE + " = '" + gasType + "'";
				    String priceOrder = GasFinderProvider.KEY_DATE + " DESC";
				    Cursor cursorPrice = getContentResolver().query(GasFinderProvider.CONTENT_URI_PRICES, null, where, null, priceOrder);
			    
				    DecimalFormat df = new DecimalFormat();
				    DecimalFormatSymbols symbols = new DecimalFormatSymbols();
				    symbols.setDecimalSeparator(',');
				    symbols.setGroupingSeparator(' ');
				    df.setDecimalFormatSymbols(symbols);
			    
				    if(cursorPrice.getCount() != 0) {
				    	cursorPrice.moveToNext();
						String priceValueString = cursorPrice.getString(3);
						
						double priceValue;
						try {
							priceValue = (Double) df.parse(priceValueString);
						} catch (ParseException e) {
							priceValue = 0d;
							Log.d(getClass().getName(), "Exception caughted " + e.getLocalizedMessage());
						}
						price = (float) priceValue;
				    } 
				    
					Double longitude = xCoord * 1E6;
					Double latitude = yCoord * 1E6;
					String stationPerimeter = getRectPerimeterByCoord(Double.valueOf(xCoord),Double.valueOf(yCoord),5);
					GeoPoint geoPoint = new GeoPoint(latitude.intValue(), longitude.intValue());
					OverlayItem overlayitem = new OverlayItem(geoPoint,
							String.valueOf(price), true + "@@" + stationPerimeter + "@@" + xCoord + "@@" + yCoord);
					
					favouriteGasStationsOverlay.addOverlay(overlayitem, drawable);
				}
			}
			
			overlays.add(favouriteGasStationsOverlay);
			myMapView.invalidate();
		}
	}
	
	public Location getMyLocation() {
		return myLocation;
	}
	
	public Location getMyLocationOverlay() {
        Location location = new Location("dummyGPS");
        if(myLocationOverlay.getLastLocationKnown() == null) {
        	myLocationOverlay.setLastLocationKnown(myLocation);
        }
        
        location.setLongitude(myLocationOverlay.getLastLocationKnown().getLongitudeE6() / 1E6);
        location.setLatitude(myLocationOverlay.getLastLocationKnown().getLatitudeE6() / 1E6);

		return location;
	}

}
